﻿package core.image
{
    import flash.display.*;
    import flash.geom.*;

    public class CurveGroup extends Object
    {
        public const RED:int = 1;
        public const GREEN:int = 2;
        public const BLUE:int = 3;
        public const RGB:int = 0;
        public var RGB_G_LUT:Array;
        public var RGB_R_LUT:Array;
        public var curves:Sprite;
        public var channelCurves:Array;
        public var CHANNEL_SHIFT:Array;
        public var CURVE_COLOR:Array;
        public var bc:BitmapData;
        public var chart:BitmapData;
        public var modifiedMap:BitmapData;
        public var showhistogram:Boolean = false;
        public var curChannel:int;
        public var HIST_COLOR:Array;
        private var matrix:Matrix;

        public function CurveGroup(param1:BitmapData, param2:BitmapData, param3:Sprite)
        {
            this.channelCurves = new Array(4);
            this.modifiedMap = param1;
            this.bc = param1.clone();
            this.chart = param2;
            this.curves = param3;
            this.RGB_R_LUT = new Array(256);
            this.RGB_G_LUT = new Array(256);
            this.CURVE_COLOR = [4286019447, 4294901760, 4278255360, 4278190335];
            this.HIST_COLOR = [1601664887, 1610547200, 1593900800, 1593835775];
            this.CHANNEL_SHIFT = [0, 16, 8, 0];
            this.curChannel = this.RGB;
            this.channelCurves[this.curChannel] = new ChannelCurve(this.CHANNEL_SHIFT[this.curChannel]);
            this.matrix = new Matrix();
            this.matrix.scale(150 / param1.width, 150 / param1.height);
            this.Update();
            return;
        }// end function

        public function UpdateLUTS() : void
        {
            var _loc_1:int = 0;
            this.channelCurves[this.curChannel].Update();
            if (this.curChannel == this.RGB)
            {
                _loc_1 = 0;
                while (_loc_1 < this.channelCurves[this.curChannel].LUT.length)
                {
                    
                    this.RGB_G_LUT[_loc_1] = this.channelCurves[this.curChannel].LUT[_loc_1] << 8;
                    this.RGB_R_LUT[_loc_1] = this.RGB_G_LUT[_loc_1] << 8;
                    _loc_1++;
                }
            }
            return;
        }// end function

        public function ApplyPaletteMap() : void
        {
            this.modifiedMap.copyPixels(this.bc, this.bc.rect, this.bc.rect.topLeft);
            this.modifiedMap.paletteMap(this.modifiedMap, this.modifiedMap.rect, this.modifiedMap.rect.topLeft, this.GetChannelLUT(this.RED), this.GetChannelLUT(this.GREEN), this.GetChannelLUT(this.BLUE));
            this.modifiedMap.paletteMap(this.modifiedMap, this.modifiedMap.rect, this.modifiedMap.rect.topLeft, this.RGB_R_LUT, this.RGB_G_LUT, this.GetChannelLUT(this.RGB));
            return;
        }// end function

        public function GetChannelLUT(core.image:CurveGroup:int) : Array
        {
            if (this.channelCurves[core.image:CurveGroup])
            {
                return this.channelCurves[core.image:CurveGroup].LUT;
            }
            return null;
        }// end function

        public function UpdateHistograms() : void
        {
            var _loc_1:int = 0;
            var _loc_2:int = 0;
            var _loc_3:int = 0;
            var _loc_4:uint = 0;
            var _loc_5:int = 0;
            var _loc_6:int = 0;
            var _loc_7:int = 0;
            var _loc_8:int = 0;
            var _loc_10:int = 0;
            var _loc_12:int = 0;
            var _loc_9:* = this.channelCurves[this.curChannel].histogram;
            while (_loc_10 < 256)
            {
                
                _loc_9[_loc_10] = 0;
                _loc_10++;
            }
            var _loc_11:* = new BitmapData(150, 150, true, 16777215);
            _loc_11.draw(this.modifiedMap, this.matrix);
            while (_loc_12 < _loc_11.width)
            {
                
                _loc_7 = 0;
                while (_loc_7 < _loc_11.height)
                {
                    
                    _loc_4 = _loc_11.getPixel32(_loc_12, _loc_7);
                    if ((_loc_4 >>> 24 & 255) > 0)
                    {
                        _loc_1 = _loc_4 >>> 16 & 255;
                        _loc_2 = _loc_4 >>> 8 & 255;
                        _loc_3 = _loc_4 & 255;
                        switch(this.curChannel)
                        {
                            case this.RED:
                            {
                                (_loc_9[_loc_1] + 1);
                                break;
                            }
                            case this.BLUE:
                            {
                                (_loc_9[_loc_3] + 1);
                                break;
                            }
                            case this.GREEN:
                            {
                                (_loc_9[_loc_2] + 1);
                                break;
                            }
                            case this.RGB:
                            {
                                (_loc_9[_loc_1] + 1);
                                (_loc_9[_loc_3] + 1);
                                (_loc_9[_loc_2] + 1);
                                break;
                            }
                            default:
                            {
                                break;
                            }
                        }
                    }
                    _loc_7++;
                }
                _loc_12++;
            }
            var _loc_13:* = 256 * 256;
            var _loc_14:* = new Array(0, 0, 0, 0);
            var _loc_15:* = this.HIST_COLOR[this.curChannel];
            _loc_10 = 0;
            while (_loc_10 < _loc_9.length)
            {
                
                _loc_8 = 0;
                while (_loc_8 < 4)
                {
                    
                    if (_loc_14[_loc_8] < _loc_9[_loc_10])
                    {
                        _loc_14[_loc_8] = _loc_9[_loc_10];
                        break;
                    }
                    _loc_8++;
                }
                _loc_10++;
            }
            _loc_6 = _loc_14[0];
            var _loc_16:* = 1;
            while (_loc_16 < 4)
            {
                
                if (_loc_6 > _loc_14[_loc_16])
                {
                    _loc_6 = _loc_14[_loc_16];
                }
                _loc_16 = _loc_16 + 1;
            }
            this.chart.fillRect(this.chart.rect, 16777215);
            _loc_12 = 0;
            while (_loc_12 < 256)
            {
                
                _loc_5 = Math.round(1 * _loc_9[_loc_12] * 256 / _loc_6);
                if (_loc_5 > 256)
                {
                    _loc_5 = 256;
                }
                _loc_7 = _loc_5;
                while (_loc_7 >= 0)
                {
                    
                    this.chart.setPixel32(_loc_12, 256 - _loc_7, _loc_15);
                    _loc_7 = _loc_7 - 1;
                }
                _loc_12++;
            }
            return;
        }// end function

        public function SetCurrentChannel(matrix:int) : void
        {
            this.curChannel = matrix;
            if (!this.channelCurves[this.curChannel])
            {
                this.channelCurves[this.curChannel] = new ChannelCurve(this.CHANNEL_SHIFT[this.curChannel]);
            }
            return;
        }// end function

        public function Preset(matrix:Array) : void
        {
            var _loc_2:int = 0;
            this.channelCurves = new Array(4);
            while (_loc_2 < matrix.length)
            {
                
                this.channelCurves[_loc_2] = new ChannelCurve(this.CHANNEL_SHIFT[_loc_2]);
                if (matrix[_loc_2])
                {
                    if (matrix[_loc_2][0] != 0 || matrix[_loc_2][1] != 255 || matrix[_loc_2][2] != 255 || matrix[_loc_2][3] != 0)
                    {
                        this.channelCurves[_loc_2].Preset(matrix[_loc_2]);
                    }
                }
                _loc_2++;
            }
            this.SetCurrentChannel(this.curChannel);
            return;
        }// end function

        public function Update() : void
        {
            this.curves.graphics.clear();
            this.UpdateLUTS();
            this.DrawCurves();
            this.DrawPoints();
            this.ApplyPaletteMap();
            if (this.showhistogram)
            {
                this.UpdateHistograms();
            }
            return;
        }// end function

        private function DrawPoints() : void
        {
            var _loc_1:Point = null;
            var _loc_2:int = 0;
            this.curves.graphics.beginFill(this.CURVE_COLOR[this.curChannel]);
            while (_loc_2 < this.channelCurves[this.curChannel].points.length)
            {
                
                _loc_1 = this.channelCurves[this.curChannel].points[_loc_2];
                this.curves.graphics.drawRect(_loc_1.x - 3, _loc_1.y - 3, 5, 5);
                _loc_2++;
            }
            this.curves.graphics.endFill();
            return;
        }// end function

        private function DrawCurves() : void
        {
            var _loc_1:int = 0;
            while (_loc_1 < this.channelCurves.length)
            {
                
                if (this.channelCurves[_loc_1] && _loc_1 != this.curChannel)
                {
                    this.AddCurve(_loc_1);
                }
                _loc_1++;
            }
            this.AddCurve(this.curChannel);
            return;
        }// end function

        private function AddCurve(matrix:int) : void
        {
            var _loc_2:int = 0;
            var _loc_3:int = 0;
            this.curves.graphics.lineStyle(matrix == this.curChannel ? (2) : (1), this.CURVE_COLOR[matrix]);
            this.curves.graphics.moveTo(0, this.channelCurves[matrix].splineVals[0]);
            while (_loc_3 < this.channelCurves[matrix].splineVals.length)
            {
                
                _loc_2 = this.channelCurves[matrix].splineVals[_loc_3];
                this.curves.graphics.lineTo(_loc_3, _loc_2);
                _loc_3++;
            }
            return;
        }// end function

    }
}
